package be.groept.ace.enquete.model.dao;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import be.groept.ace.enquete.model.exceptions.DAOException;

public class JDBCDAOManager implements DAOManager {

	private DataSource dataSource = null;
	private Connection connection = null;
	private UserDAO  userDAO  = null;
	private SurveyDAO surveyDAO = null;
	private QuestionDAO questionDAO = null;
	  
	public JDBCDAOManager(DataSource dataSource) {
		this.dataSource = dataSource;
	}
	@Override
	public UserDAO getUserDAO() throws DAOException{
		if (userDAO == null) {
			userDAO = new UserDAOJDBCImpl(getTxConnection());
		}
		return userDAO;
	}
	
	@Override
	public QuestionDAO getQuestionDAO() throws DAOException {
		if(questionDAO == null ) {
			questionDAO = new QuestionDAOJDBCImpl(getTxConnection());
		}
		return questionDAO;
	}
	
	@Override
	public SurveyDAO getSurveyDAO() throws DAOException {
		if (surveyDAO == null) {
			surveyDAO = new SurveyDAOJDBCImpl(getTxConnection(), getUserDAO(), getQuestionDAO());
		}
		return surveyDAO;
	}
	
	
	private Connection getConnection() throws DAOException {
		if(connection == null){
			try {
				connection = dataSource.getConnection();
			}catch (SQLException sqle) {
				throw new DAOException(sqle);
			}
		}
		return connection;
	}
	
	private Connection getTxConnection() throws DAOException{
		try {
			getConnection().setAutoCommit(false);
		} catch (SQLException sqle) {
			throw new DAOException(sqle);
		}
		return getConnection();
	}
	
	@Override
	public Object transaction(DAOCommand command) throws DAOException{
		try{
			Object returnValue = command.execute(this);
			getConnection().commit();
			return returnValue;
		} catch(Exception e){
			try {
				getConnection().rollback();
			}catch(SQLException sqle) {
				//log severe 
			}
			throw new DAOException(e);
		} finally {
			try {
				getConnection().setAutoCommit(true);
			}catch (SQLException sqle) {
				//log severe
			}
		}
	}
	
	@Override
	public Object executeAndClose(DAOCommand command) throws DAOException{
		try{
			return command.execute(this);
		} finally {
			try {
				getConnection().close();
			}catch(SQLException sqle) {
				throw new DAOException(sqle);
			}
		}
	}
	
	@Override
	public Object transactionAndClose(final DAOCommand command) throws DAOException{
		return executeAndClose(new DAOCommand(){
			public Object execute(DAOManager manager) throws DAOException {
				return manager.transaction(command);
			}
		});
	}

}
